﻿using System;

using System.Collections.Generic;
using System.IO;

using System.Data;
using Microsoft.Office.Server;
using Microsoft.Office.Server.Search.Administration;

namespace SearchCrawlLogViewer
{
    class CrawlLogFilterContext
    {
        #region Member Variables

        LogViewer _logViewer;
        CrawlLogFilters _crawlLogFilters;
        List<CrawlLogData> _crawlLogDataCache = null;

        int _startAt = 0;
        int _currentPageNumber = 0;

        CatalogType _catalogType;
        MessageType _messageType;
        int _contentSourceID;
        string _hostNamePath;
        int _totalEntries;
        DateTime _startLogTime;
        DateTime _endLogTime;
        int _statusMessageId;

        #endregion

        #region Properties

        public LogViewer LogViewer
        {
            get { return _logViewer; }
        }

        public CrawlLogFilters CrawlLogFilters
        {
            get { return _crawlLogFilters; }
        }

        public int StartAt
        {
            get { return _startAt; }
            set
            {
                _startAt = value;
                _crawlLogFilters.AddFilter(CrawlLogFilterProperty.StartAt, value);
            }
        }

        public int CurrentPageNumber
        {
            get { return _currentPageNumber; }
            set { _currentPageNumber = value; }
        }

        public CatalogType CatalogType
        {
            get { return _catalogType; }
            set
            {
                _catalogType = value;
                _crawlLogFilters.AddFilter(value);
            }
        }

        public MessageType MessageType
        {
            get { return _messageType; }
            set
            {
                _messageType = value;
                _crawlLogFilters.AddFilter(value);
            }
        }

        public int ContentSourceID
        {
            get { return _contentSourceID; }
            set
            {
                _contentSourceID = value;
                _crawlLogFilters.AddFilter(CrawlLogFilterProperty.ContentSourceId, value);
            }
        }

        public int StatusMessageId
        {
            get { return _statusMessageId; }
            set
            {
                _statusMessageId = value;
                _crawlLogFilters.AddFilter(CrawlLogFilterProperty.MessageId, value);
            }
        }

        public string HostNamePath
        {
            get { return _hostNamePath; }
            set
            {
                _hostNamePath = value;
                _crawlLogFilters.AddFilter(CrawlLogFilterProperty.HostName, StringFilterOperator.Contains, value);
            }
        }

        public int TotalEntries
        {
            get { return _totalEntries; }
            set
            {
                _totalEntries = value;
                _crawlLogFilters.AddFilter(CrawlLogFilterProperty.TotalEntries, value);
            }
        }

        #endregion

        #region Methods

		public CrawlLogFilterContext(SearchServiceApplication contentSSA)
        {
			_logViewer = new LogViewer(contentSSA);
            _crawlLogFilters = new CrawlLogFilters();
            _crawlLogDataCache = new List<CrawlLogData>();
        }

        /// <summary>
        /// Clears the collection of crawl log filters.
        /// </summary>
        public void ResetCrawlLogFilters()
        {
            _crawlLogFilters = new CrawlLogFilters();
        }

        /// <summary>
        /// Clears the cache of CrawlLogData objects.
        /// </summary>
        public void ResetCrawlLogDataCache()
        {
            _crawlLogDataCache.Clear();
        }

        /// <summary>
        /// Returns a CrawlLogData instance representing the crawl log entries
        /// for the current page.
        /// </summary>
        /// <returns></returns>
        public CrawlLogData GetCrawlLogData()
        {
            // If the crawl log data for the current page has not been
            // cached yet then...
            if (_currentPageNumber > _crawlLogDataCache.Count)
            {
                // Go get it and cache it.
                int nextStart = 0;

                // Get the index to start at from the end index of the
                //last cached page.
                if (_crawlLogDataCache.Count > 0)
                    StartAt =
                        _crawlLogDataCache[
                            _crawlLogDataCache.Count - 1].EndIndex + 1;

                // Use the LogViewer instance to request the filtered
                // view of log entries.
                DataTable crawlLogDataTable =
                    _logViewer.GetCurrentCrawlLogData(
                        _crawlLogFilters, out nextStart);

                // Trim the result set if we got back more than the
                // requested number of entries.
                while (crawlLogDataTable.Rows.Count > TotalEntries)
                    crawlLogDataTable.Rows.RemoveAt(
                        crawlLogDataTable.Rows.Count - 1);
               
                // Create a new CrawlLogData based on the results and
                // add it to the cache.
                CrawlLogData crawlLogData =
                    new CrawlLogData(
                        crawlLogDataTable, _startAt, nextStart == -1);

                _crawlLogDataCache.Add(crawlLogData);

                // Return the crawl log data so it can be displayed.
                return crawlLogData;
            }
            else
                // Return the cached crawl log data.
                return _crawlLogDataCache[_currentPageNumber - 1];    
        }

        public void SetLogTimeFilters(DateTime startLogTime, DateTime endLogTime)
        {
            _startLogTime = startLogTime;
            _endLogTime = endLogTime;

            _crawlLogFilters.AddFilter(startLogTime, endLogTime);
        }

        public bool DoesCrawlLogDataExist()
        {
            return _crawlLogDataCache.Count > 0;
        }

        #endregion
    }
}
